package com.gwclh.personnel.controller;


import cn.hutool.core.lang.Assert;
import cn.hutool.crypto.SecureUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.gwclh.personnel.bean.ResultVo;
import com.gwclh.personnel.common.annotation.OperLog;
import com.gwclh.personnel.common.constants.OperLogConstants;
import com.gwclh.personnel.domain.PageDomain;
import com.gwclh.personnel.entity.User;
import com.gwclh.personnel.service.IUserService;
import com.gwclh.personnel.utils.ShiroUtil;
import io.swagger.annotations.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.authz.annotation.RequiresRoles;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.util.List;

/**
 * <p>
 * 系统用户表，用户由超级管理员添加，使用用户名、密码登录 前端控制器
 * </p>
 *
 * @author gzhhh
 * @since 2020-07-24
 */


@RestController
@RequestMapping("/users")
@Api(tags = "用户相关接口")
@Validated//数据校验
@Slf4j
public class UserController extends BaseController {

    @Autowired
    IUserService userService;

    @GetMapping("/{id}")
    @ApiOperation(value = "根据id获取用户信息接口,示例用")
    @ApiImplicitParam(name = "id",value = "用户id",dataType = "Integer",paramType = "path",required = true)
    public ResultVo getUserById(@PathVariable(value = "id") Integer id){
        Assert.isTrue(ShiroUtil.getProfile().getId()==id,"您无权限操作");
        User user = userService.getById(id);
        Assert.notNull(user, "找不到当前用户");  //Assert.notNull可以理解为如果user不为空，继续往下执行，如果为空，抛出异常，全局捕获异常，再返回给前端
        Assert.isTrue(user.getStatus(), "当前用户已被冻结");
        return ResultVo.success(user);
    }

    @GetMapping("")
    @ApiOperation(value = "分页查询用户列表")
    @RequiresRoles({"ROLE_admin"})//授权方法中给用户添加角色
    public ResultVo listUser(User user, HttpServletRequest request) {
        PageDomain pageDomain = getPageParams(request);
        return userService.listUsers(pageDomain, user);
    }

    @PostMapping("")
    @ApiOperation(value = "添加用户")
    @OperLog(operModule = OperLogConstants.OPER_LOG_MODULE_USER, operType = OperLogConstants.OPER_LOG_POST, operDesc = "添加用户")
    @RequiresRoles({"ROLE_admin"})
    public ResultVo insertUser(@Validated @RequestBody User user) {
        return userService.insertUser(user);
    }

    @DeleteMapping("/{id}")
    @ApiOperation(value = "删除单个用户")
    @OperLog(operModule = OperLogConstants.OPER_LOG_MODULE_USER, operType = OperLogConstants.OPER_LOG_DELETE, operDesc = "删除单个用户")
    @ApiImplicitParam(name = "id", value = "用户id", dataType = "Integer", paramType = "path", required = true)
    @RequiresRoles({"ROLE_admin"})
    public ResultVo delUser(@PathVariable(value = "id") Integer id) {
        // 无法删除用户名为admin的用户
        Assert.isTrue(id != 1, "无法删除该用户");
        Assert.isTrue(userService.removeById(id), "删除用户失败");
        userService.delRedisUser(id);
        return ResultVo.success();
    }

    @DeleteMapping("")
    @ApiOperation(value = "根据ids数组批量删除用户")
    @OperLog(operModule = OperLogConstants.OPER_LOG_MODULE_USER, operType = OperLogConstants.OPER_LOG_DELETE, operDesc = "批量删除用户")
    @ApiImplicitParam(name = "ids", value = "用户id数组", dataType = "List", paramType = "body", required = true)
    @RequiresRoles({"ROLE_admin"})
    public ResultVo delListUser(@RequestBody(required = true) List<Integer> ids) {

        // 过滤掉id为1的用户
        int tempIdIndex = -1;
        for (int i = 0; i < ids.size(); i++) {
            if (ids.get(i) == 1) {
                tempIdIndex = i;
            }
        }
        if (tempIdIndex != -1) {
            ids.remove(tempIdIndex);
        }
        Assert.isTrue(ids.size() != 0, "删除失败");

        // 删除掉id为1的
        Assert.isTrue(userService.removeByIds(ids), "批量删除用户失败");

        // 如果用户信息在redis中，删除该用户在redis的信息
        ids.stream().forEach(id -> {
            userService.delRedisUser(id);
        });

        return ResultVo.success();
    }

    @PatchMapping("/status/{id}")
    @ApiOperation(value = "更改用户状态")
    @OperLog(operModule = OperLogConstants.OPER_LOG_MODULE_USER, operType = OperLogConstants.OPER_LOG_PATCH, operDesc = "更改用户状态")
    @ApiImplicitParam(name = "id", value = "用户id", dataType = "Integer", paramType = "path", required = true)
    @RequiresRoles({"ROLE_admin"})
    public ResultVo updateUserStatus(@PathVariable(value = "id") Integer id) {
        Assert.isTrue(id != 1, "无法更改该用户状态");
        User user = userService.getById(id);
        Assert.notNull(user, "当前用户不存在");
        Assert.isTrue(userService.update(new UpdateWrapper<User>().eq("id", id).set("status", !user.getStatus())), "更改用户状态失败");
        // 删除用户在redis的信息，下次访问重新获取数据库的信息，避免更改数据后，用户可以继续访问接口
        userService.delRedisUser(id);
        return ResultVo.success();
    }

    @PatchMapping("/role/{id}")
    @ApiOperation(value = "更改用户角色")
    @OperLog(operModule = OperLogConstants.OPER_LOG_MODULE_USER, operType = OperLogConstants.OPER_LOG_PATCH, operDesc = "更改用户角色")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "id", value = "用户id", dataType = "Integer", paramType = "path", required = true),
            @ApiImplicitParam(name = "role", value = "新角色", dataType = "String", paramType = "query", required = true)
    })
    @RequiresRoles({"ROLE_admin"})
    public ResultVo updateUserRole(@PathVariable(value = "id") Integer id, @RequestParam(value = "role") String role) {
        Assert.isTrue(role.equals("ROLE_admin") || role.equals("ROLE_user"), "参数错误");
        Assert.isTrue(id != 1, "无法该更改用户角色");
        User user = userService.getById(id);
        Assert.notNull(user, "当前用户不存在");
        Assert.isTrue(userService.update(new UpdateWrapper<User>().eq("id", id).set("role", role)), "更改用户角色失败");
        userService.delRedisUser(id);
        return ResultVo.success();
    }

    @PatchMapping("/password")
    @ApiOperation(value = "用户修改密码")
    @OperLog(operModule = OperLogConstants.OPER_LOG_MODULE_USER,operType = OperLogConstants.OPER_LOG_PATCH,operDesc = "用户修改密码")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "oPassword",value = "旧密码",dataType = "String",paramType = "query"),
            @ApiImplicitParam(name = "nPassword",value = "新密码",dataType = "String",paramType = "query")
    })
    public ResultVo updateUserPassword(@RequestParam("oPassword") String oPassword,@RequestParam("nPassword") String nPassword){
        Integer currID = ShiroUtil.getProfile().getId();
        User user = userService.getById(currID);
        Assert.notNull(user,"查无此用户");
        Assert.isTrue(SecureUtil.md5(oPassword).equals(user.getPassword()),"旧密码错误");
        Assert.isTrue(userService.update(new UpdateWrapper<User>().eq("id",currID).set("password",SecureUtil.md5(nPassword))),"更改密码失败");
        return ResultVo.success();
    }


    @PutMapping("")
    @ApiOperation(value = "用户更新")
    @OperLog(operModule = OperLogConstants.OPER_LOG_MODULE_USER,operType = OperLogConstants.OPER_LOG_PUT,operDesc = "用户更新")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "user",value = "用户对象",dataType = "User",paramType = "body")
    })
    public ResultVo updateUser(@RequestBody User user){
        // 判断操作人是否是当前用户
        Assert.isTrue(user.getId() == ShiroUtil.getProfile().getId(),"您无权限操作");

        // 判断新用户名是否已存在
        User user1 = userService.getOne(new QueryWrapper<User>().ne("id",user.getId()).eq("username",user.getUsername()));
        Assert.isNull(user1,"该用户名已存在");

        userService.updateById(user);
        userService.delRedisUser(user.getId());
        return ResultVo.success(user);
    }

}
